iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
Software Development

歡迎來到 GIS 的世界!30 天從後端開始學 GIS系列 第 14

一起來用 NetTopologySuite 處理 Shapefile 吧! - 1 讀取和建立

  • 分享至 

  • xImage
  •  

文章已同步發表至 Medium

NetTopologySuite.IO.Esri 加入我們的專案之後,就可以開始對我們的 Shapefile 進行操作了。這裡使用政府開放平臺所提供的資料作為範例,也是我們之後實作會使用到的其中一個檔案。

讀取

using NetTopologySuite.IO.Esri;

foreach (var feature in Shapefile.ReadAllFeatures(@"shapefile path"))
{
    foreach (var attrName in feature.Attributes.GetNames())
    {
        Console.WriteLine($"{attrName,10}: {feature.Attributes[attrName]}");
    }

    // Console.WriteLine($"     SHAPE: {feature.Geometry.AsText()}");
    Console.WriteLine($"      SRID: {feature.Geometry.SRID}");
    Console.WriteLine();
}

根據 GitHub 上的寫法,只要簡單的這幾行,馬上就能讀取 Shapefile 了!執行後的結果如下:

從讀取後的結果可以看到,之前讓我們在 GDAL 中痛苦不已的中文,在 NetTopologySuite 上可以好好的正常顯示!(痛哭流涕)

另外也可以看到,NetTopologySuite 在寫法上相對來說更為簡潔,一開始可以選擇直接讀取 Feature 就好,再透過欄位名稱從 Atrributes 取得 Field 的值,不像 GDAL 還需要從 Layer 先取得 Layer 的數量跑回圈,接著從 Layerlayer.GetNextFeature() 才能開始讀資料,可讀性比起 GDAL 高出許多。

輸出

using System.Text;
using NetTopologySuite.Features;
using NetTopologySuite.IO;
using NetTopologySuite.IO.Esri;

var features = new List<Feature>();
var wktReader = new WKTReader();

var fcuGeometry = wktReader.Read(
    "POLYGON((214094.18733422138 2675204.397772933,214613.04806256315 2675203.096234374,214612.0331897791 2674795.5200602347,214093.15758024747 2674796.8214499434,214094.18733422138 2675204.397772933))");

var fcuAttributes = new AttributesTable();
fcuAttributes.Add("日期", DateTime.Today);
fcuAttributes.Add("地點", "逢甲大學");

var fcuFeature = new Feature(fcuGeometry, fcuAttributes);
features.Add(fcuFeature);

var nightMarketGeometry = wktReader.Read(
    "POLYGON((213945.3342767608 2674876.347737663,214097.93845940504 2674873.793433358,214099.4943339883 2674626.6362772766,214474.48457545802 2674625.694102451,214511.39058478415 2674562.7289472898,214223.11502519806 2674368.326804782,213983.77470059253 2674559.719947559,213945.3342767608 2674876.347737663))");
var nightMarketAttributes = new AttributesTable();
nightMarketAttributes.Add("日期", DateTime.Today);
nightMarketAttributes.Add("地點", "逢甲夜市");
var nightMarketFeature = new Feature(nightMarketGeometry, nightMarketAttributes);
features.Add(nightMarketFeature);

Shapefile.WriteAllFeatures(features, @"files\create.shp", Encoding.UTF8);

根據 GitHub 上的範例,一樣可以簡單的利用使用 Shapefile.WriteAllFeatures() 來建立。不過,範例上建立的是 MultiLine ,把他修改成 Polygon 之後,執行時遇到了一個錯誤:

這個 Exception 哪裡來

一開始看到錯誤原因的時候真的覺得很茫然 ? 我很確定我的 WKT 是 Polygon 沒有錯,為甚麼 Exception 會告訴我我想把 Polygon 轉換成 Multi Polygon 呢 ?

於是開啟 debbug mode,順著程式碼一行一行往下找,終於在 Shapefile.cs 中找到一點線索。在最後要使用 Writer 寫入的時候,他所建立的 Writer 泛型所吃的類別竟然只有 Multi Polygon 的選項 ?

也就是說,就算我的 Geometry 型別是 Polygon ,但 Writer 依舊會以 MultiPolygon 建立,但因為型別不同,所以在使用 Writer 前他會一直想把我的型別轉換成 MultiPolygon ,才會一直噴出 Exception。

但原始碼裡,Writer 只有針對 MultiPolygon 去進行寫入的方法,也就等於所有 Polygon 相關的類別:PolygonPolygonMPolygonZPolygonZM 都會使用 Multi Polygon Writer 去建立。

References


上一篇
一起來用 NetTopologySuite 處理 Shapefile 吧! - 0 準備
下一篇
一起來用 NetTopologySuite 處理 Shapefile 吧! - 2 修正
系列文
歡迎來到 GIS 的世界!30 天從後端開始學 GIS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言